// Error Handling (错误处理) 示例
program ErrorHandlingExample;

{$mode objfpc}{$H+}

uses
  SysUtils;

// 自定义异常类型
type
  ECustomException = class(Exception)
  public
    constructor Create(const Msg: string);
  end;

constructor ECustomException.Create(const Msg: string);
begin
  inherited Create('自定义异常: ' + Msg);
end;

// 可能引发异常的函数
function DivideNumbers(A, B: Double): Double;
begin
  if B = 0 then
    raise EDivByZero.Create('除数不能为零')
  else
    Result := A / B;
end;

// 演示基本异常处理
procedure DemonstrateBasicExceptionHandling;
var
  A, B, Result: Double;
begin
  WriteLn('=== 基本异常处理示例 ===');
  try
    WriteLn('请输入被除数: ');
    ReadLn(A);
    WriteLn('请输入除数: ');
    ReadLn(B);
    
    Result := DivideNumbers(A, B);
    WriteLn('结果: ', A:0:2, ' / ', B:0:2, ' = ', Result:0:2);
  except
    on E: EDivByZero do
      WriteLn('捕获到除零异常: ', E.Message);
    on E: EInvalidOp do
      WriteLn('捕获到无效操作异常: ', E.Message);
    on E: Exception do
      WriteLn('捕获到其他异常: ', E.ClassName, ' - ', E.Message);
  end;
  WriteLn;
end;

// 演示资源清理（try...finally）
procedure DemonstrateResourceCleanup;
var
  FileStream: TextFile;
  FileName: string;
begin
  WriteLn('=== 资源清理示例 ===');
  FileName := 'test.txt';
  
  AssignFile(FileStream, FileName);
  try
    Rewrite(FileStream);
    try
      WriteLn(FileStream, '这是测试文件内容');
      WriteLn('成功写入文件: ', FileName);
    finally
      CloseFile(FileStream);
      WriteLn('文件已关闭');
    end;
  except
    on E: Exception do
    begin
      WriteLn('文件操作异常: ', E.Message);
      // 确保文件被关闭
      if FileExists(FileName) then
        CloseFile(FileStream);
    end;
  end;
  WriteLn;
end;

// 演示自定义异常
procedure DemonstrateCustomException;
begin
  WriteLn('=== 自定义异常示例 ===');
  try
    raise ECustomException.Create('这是一个测试异常');
  except
    on E: ECustomException do
      WriteLn('捕获到自定义异常: ', E.Message);
  end;
  WriteLn;
end;

// 演示异常传播
procedure InnerProcedure;
begin
  WriteLn('内层过程引发异常');
  raise Exception.Create('内层异常');
end;

procedure OuterProcedure;
begin
  WriteLn('外层过程调用内层过程');
  InnerProcedure;
end;

procedure DemonstrateExceptionPropagation;
begin
  WriteLn('=== 异常传播示例 ===');
  try
    OuterProcedure;
  except
    on E: Exception do
      WriteLn('在外层捕获到异常: ', E.Message);
  end;
  WriteLn;
end;

// 演示 I/O 错误处理
procedure DemonstrateIOErrorHandling;
var
  FileStream: TextFile;
  FileName: string;
begin
  WriteLn('=== I/O 错误处理示例 ===');
  {$I-} // 关闭自动 I/O 检查
  FileName := 'nonexistent_file.txt';
  AssignFile(FileStream, FileName);
  Reset(FileStream);
  {$I+} // 重新开启自动 I/O 检查
  
  if IOResult <> 0 then
    WriteLn('无法打开文件: ', FileName, ' (文件可能不存在)')
  else
  begin
    WriteLn('文件打开成功');
    CloseFile(FileStream);
  end;
  WriteLn;
end;

begin
  WriteLn('=== Pascal 错误处理示例 ===');
  WriteLn;
  
  // 演示各种错误处理技术
  DemonstrateBasicExceptionHandling;
  DemonstrateResourceCleanup;
  DemonstrateCustomException;
  DemonstrateExceptionPropagation;
  DemonstrateIOErrorHandling;
  
  WriteLn('错误处理示例完成。');
  ReadLn;
end.